package com.sadhoc.router;

import java.io.IOException;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.Hashtable;

import com.sadhoc.router.pdu.HDPacket;
import com.sadhoc.router.util.Debug;
import com.sadhoc.sockets.TCPSender;
import com.sadhoc.sockets.UDPSender;

public class PacketSender {
	
	private Hashtable<String, TCPSender> tcpSockets = null;
	private UDPSender udpSender;
	private int port = 0;
	
	/*
	 * Constructor
	 */
	public PacketSender(int port) throws SocketException {
		
		tcpSockets = new Hashtable<String, TCPSender>();
		this.port = port;
		
		udpSender = new UDPSender();
		new Thread(udpSender).start();
			
		Debug.printBasic("PacketSender initialized");
				
	}
			
	/*
	 * Instantiates a TCPSender for the destination IP if 
	 * one was previously not established or the session has timed out.
	 * 
	 * We have to keep track because TCP is connection-oriented,
	 * so there's a possibility new packets may try to be sent while
	 * the session is still open, which is why messages are queue in the TCPSender
	 */
	public boolean sendTCP(String destIP, HDPacket hdp) {
		
		try {
			
			TCPSender tcps;
			
			if (tcpSockets.containsKey(destIP)) {
				tcps = (TCPSender) tcpSockets.get(destIP);
				
				if (!tcps.isConnected()) {
					tcps.close();
					tcps = new TCPSender(destIP, port);
					new Thread(tcps).start();
					tcpSockets.put(destIP, tcps);
				}
				
			}
			else {
				tcps = new TCPSender(destIP, port);
				new Thread(tcps).start();
				tcpSockets.put(destIP, tcps);	
			}
			
			tcps.send(hdp);
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return false;
		
	}
	
	/*
	 * Sends the UDP Message
	 */
	public boolean sendUDP(String destIP, HDPacket hdp) {
				
		try {
			udpSender.send(destIP, port, hdp.getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		}
	
		return false;
		
	}

	/*
	 * Stops everything
	 */
	public void stop() {

		udpSender.stop();
		for (Enumeration<String> e = tcpSockets.keys(); e.hasMoreElements();)
			tcpSockets.get(e.nextElement()).close();
		
	}
	
	public void closeSocket(String destIP) {
		if (tcpSockets.containsKey(destIP)) {
			tcpSockets.get(destIP).close();
			tcpSockets.remove(destIP);
		}
	}
	
}
